package de.hsowl.tod4a.client;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import de.hsowl.tod4a.client.query.Comparator;
import de.hsowl.tod4a.client.transaction.Transaction;
import de.hsowl.tod4a.global.exception.ObjectDatabaseException;
import de.hsowl.tod4a.global.listener.DataChangedListener;
import de.hsowl.tod4a.global.model.ClientProperty;
import de.hsowl.tod4a.global.model.ObjectMap;
import de.hsowl.tod4a.global.util.Mapper;

/**
 * Represents a remote connection.
 * 
 * 
 * @author Sebastian Witt
 * 
 */
public class RemoteConnectionInterface extends ConnectionInterface {

	/**
	 * Client to access a remote database
	 */
	private ObjectClient objClient = null;

	@SuppressWarnings("unused")
	private ArrayList<Transaction> transactions = new ArrayList<Transaction>();
	private Mapper mapper = new Mapper();

	public RemoteConnectionInterface(String url, int port, String username, String password, ClientProperty props)
			throws IOException, ObjectDatabaseException {
		objClient = new ObjectClient(url, port, username, password, props);
	}

	/**
	 * See {@link EntityManager#store(Object...)}
	 * 
	 * @param names
	 *            - maybe null
	 * @param objects
	 */
	public void store(String[] names, Object[] objects) {
		try {
			long time = System.currentTimeMillis();
			final List<ObjectMap> maps = objectToObjectMap(names, objects);
			System.out.println("objectToObjectMap() -> " + (System.currentTimeMillis() - time));
			if (maps != null) {
				final String xml = objectToXml(maps);
				objClient.store(xml);
			} else {
				throw new NullPointerException();
			}
		} catch (Exception e) {
			logger.error("Failure", e);
		}
	}

	/**
	 * See {@link EntityManager#get(Comparator)}
	 * 
	 * @param comp
	 * @return
	 */
	public <T> List<T> get(Comparator<T> comp, int depth) {

		return null;
	}

	/**
	 * See {@link EntityManager#getByClass(Class)}
	 * 
	 * @param clazz
	 *            a Class Object
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> getByClass(Class<?> clazz, int depth) {
		try {
			String xml = objClient.getByClass(getQueryForClass(clazz.getName(), depth));
			List<ObjectMap> list = mapper.getObjectMap(xml);
			xml = null;

			// Objekt zusammenbauen
			if (list != null && list.size() > 0) {
				List<Object> ret = buildObjects(list, clazz);
				return (List<T>) ret;
			}
		} catch (Exception e) {
			logger.error("Failure", e);
		}
		return null;
	}

	/**
	 * See {@link EntityManager#getByName(String)}
	 * 
	 * @param name
	 * @param clazz
	 * @return
	 */
	public <T> List<T> getByName(String name, int depth) {

		try {

		} catch (Exception e) {
			logger.error("Failure", e);
		}
		return null;
	}

	/**
	 * See {@link EntityManager#getByName(String, Class)}
	 * 
	 * @param name
	 * @param clazz
	 * @return
	 */
	public <T> List<T> getByName(String name, Class<?> clazz, int depth) {
		try {

		} catch (Exception e) {
			logger.error("Failure", e);
		}
		return null;
	}

	/**
	 * Executs all saved transactions and groups them
	 * 
	 * @return
	 * @throws Exception
	 */
	public boolean commitTransactions() throws ObjectDatabaseException {
		return begin;
		// TODO
	}

	/**
	 * Removes objects from database.
	 * 
	 * @param objects
	 * @throws Exception
	 */
	public void remove(Object... objects) throws Exception {
		remove(true, objects);
	}

	/**
	 * Removes objects from database.
	 * 
	 * @param children
	 * @param objects
	 * @throws ObjectDatabaseException
	 * @throws Exception
	 */
	public void remove(boolean children, Object... objects) throws ObjectDatabaseException {
		try {
			final String xml = objectToMinimalXml(children, objects);
			objClient.remove(xml);
		} catch (Exception e) {
			throw new ObjectDatabaseException("Removing failed", e);
		}
	}

	/**
	 * Adds a remote user.
	 * 
	 * @param username
	 * @param password
	 * @throws Exception
	 */
	public void addUser(String username, String password) throws ObjectDatabaseException {
		try {
			String xml = userToXml(username, password);
			objClient.addUser(xml);
		} catch (Exception e) {
			throw new ObjectDatabaseException();
		}
	}

	public void rollback(int num) throws ObjectDatabaseException {

		// TODO
	}

	/**
	 * Closes a connection to a remote host.
	 */
	public void close() {
		objClient.close();

	}

	public void removeUser(String username) throws ObjectDatabaseException {
		try {
			objClient.removeUser("<removeuser name=\"" + username + "\" />");
		} catch (Exception e) {
			throw new ObjectDatabaseException("Removing user '" + username + "' failed", e);
		}
	}

	/**
	 * See {@link EntityManager#addDataChangedListener(DataChangedListener)}
	 */
	public void addDataChangedListener(DataChangedListener listener) {
		// TODO Auto-generated method stub

	}
}
